package server

import (
	"context"
	"errors"
	"net/http"

	"github.com/google/uuid"
	"github.com/gorilla/mux"
	"github.com/sirupsen/logrus"
)

type HtpServer struct {
	*http.Server
	router *mux.Router
	name   string
}

func NewHttp(opts ...HtpOption) *HtpServer {
	srv := &HtpServer{
		&http.Server{
			Addr: ":8080",
		},
		mux.NewRouter(),
		uuid.New().String(),
	}

	for _, opt := range opts {
		opt(srv)
	}

	return srv
}

func (hs *HtpServer) Start(ctx context.Context) error {
	hs.Handler = hs.router
	logrus.Infof("http server [ %s ]: listening on address [ %s ] ...", hs.name, hs.Addr)
	err := hs.ListenAndServe()
	if !errors.Is(err, http.ErrServerClosed) {
		return err
	}
	return nil
}
func (hs *HtpServer) Stop(ctx context.Context) error {
	defer logrus.Infof("http server [ %s ]: server stopped.", hs.name)

	logrus.Infof("http server [ %s ]: address [ %s ] stopping ...", hs.name, hs.Addr)
	return hs.Shutdown(ctx)
}

func (hs *HtpServer) RouterGroup(prefix string) *RouterGroup {
	return &RouterGroup{
		router: hs.router.PathPrefix(prefix).Subrouter(),
	}
}

// GET registers a new GET route for a path with matching handler in the router.
func (hs *HtpServer) GET(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodGet)
}

// HEAD registers a new HEAD route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) HEAD(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodHead)
}

// POST registers a new POST route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) POST(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodPost)
}

// PUT registers a new PUT route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) PUT(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodPut)
}

// PATCH registers a new PATCH route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) PATCH(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodPatch)
}

// DELETE registers a new DELETE route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) DELETE(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodDelete)
}

// CONNECT registers a new CONNECT route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) CONNECT(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodConnect)
}

// OPTIONS registers a new OPTIONS route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) OPTIONS(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodOptions)
}

// TRACE registers a new TRACE route for a path with matching handler in the routerGroRouterGroup.
func (hs *HtpServer) TRACE(path string, h http.HandlerFunc) {
	hs.router.HandleFunc(path, h).Methods(http.MethodTrace)
}
